﻿using Abp.Application.Services;
using Abp.Runtime.Caching;
using DevM.Development.Resources.Dto;
using DevM.Sessions;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace DevM.Development.Resources
{
    public class ResourcesAppService : DevMAppServiceBase, IResourcesAppService
    {
        private readonly ISessionAppService sessionAppService;
        private readonly IHttpContextAccessor httpContextAccessor;
        private readonly ResourceManager resourceManager;
        private readonly ICacheManager cacheManager;

        public ResourcesAppService(ISessionAppService _sessionAppService, IHttpContextAccessor httpContextAccessor, ResourceManager resourceManager, ICacheManager cacheManager)
        {
            sessionAppService = _sessionAppService;
            this.httpContextAccessor = httpContextAccessor;
            this.resourceManager = resourceManager;
            this.cacheManager = cacheManager;
        }

       
        /// <summary>
        /// 上传资源
        /// </summary>
        /// <returns></returns>
        public async Task<UploadOutput> Post()
        {
            var files = httpContextAccessor.HttpContext.Request.Form.Files;
            var resources = new List<Resource>();
            var currentUserInfomation = await sessionAppService.GetCurrentLoginInformations();
            foreach (var file in files)
            {
                var name = file.FileName;
                var mime = file.ContentType;
                var content = new MemoryStream();
                using (var stream = file.OpenReadStream())
                {
                    byte[] buffer = new byte[stream.Length];
                    stream.Read(buffer, 0, buffer.Length);
                    content.Write(buffer, 0, buffer.Length);
                }
                var resource =await resourceManager.AddResource(new ResourceAddInfo
                {
                    Content = content,
                    Name = name,
                    Type = mime,
                    TenantId = currentUserInfomation.Tenant?.Id,
                    CreateUserId = currentUserInfomation.User?.Id??0
                });
                resources.Add(resource);
            }
            return new UploadOutput { Resources = ObjectMapper.Map<List<ResourceDto>>(resources) };
        }
        /// <summary>
        /// 下载
        /// </summary>
        /// <param name="resourceId"></param>
        /// <returns></returns>
        public async Task Get(long resourceId)
        {
            var resource =await cacheManager.GetCache("FileCache").Get($"resourceId-{resourceId}", async ()=> await resourceManager.GetResourceById(resourceId)) ;
            if (resource == null) return;
            await WriteFile(resource.Name, resource.Content, resource.Type);
        }


        private async Task WriteFile(string fileName, byte[] fileContent,string mime=null)
        {
            var _fileName = fileName;

            var httpcontext = httpContextAccessor.HttpContext;
            //如果非苹果设备则进行url编码
            if (!httpcontext.Request.Headers["UserAgent"].ToString().ToLower().Contains("mac"))
            {
                _fileName = System.Net.WebUtility.UrlEncode(_fileName);
            }

            var range = httpcontext.Request.Headers["Range"].ToString();
            if (!string.IsNullOrWhiteSpace(range))//如果遵守协议，支持断点续传
            {
                var fileLength = fileContent.Length;//文件的总大小
                long begin;//文件的开始位置
                long end;//文件的结束位置
                long.TryParse(range.Split('=')[1].Split('-')[0], out begin);
                long.TryParse(range.Split('-')[1], out end);
                end = end - begin > 0 ? end : 65536 > fileLength - 1 ? fileLength - 1 : 65536;// 如果没有结束位置，默认给一个大小

                var buffer = new byte[end - begin + 1];

                Array.Copy(fileContent, begin, buffer, 0, buffer.Length);

                //表头 表明  下载文件的开始、结束位置 和文件总大小
                httpcontext.Response.Headers.Add("Content-Range", "bytes " + begin + "-" + end + "/" + fileLength);
                httpcontext.Response.Headers.Add("Content-Length", buffer.Length.ToString());
                httpcontext.Response.ContentType = (mime != null && mime.ToLower().StartsWith("image") ? mime : "octet-stream");
                httpcontext.Response.Headers.Add("Content-Disposition", $"{(mime != null && mime.ToLower().StartsWith("image") ? "" : "attachment")};filename={_fileName}");
                httpcontext.Response.Body.Write(buffer, 0, buffer.Length);//发送 文件开始位置读取的大小
                httpcontext.Response.Body.Flush();
            }
            else
            {
                httpcontext.Response.ContentType = (mime != null && mime.ToLower().StartsWith("image") ? mime : "octet-stream") ;
                httpcontext.Response.Headers["Content-Disposition"] = $"{(mime != null && mime.ToLower().StartsWith("image") ? "" : "attachment")};filename={_fileName}";
                await httpcontext.Response.Body.WriteAsync(fileContent);
                httpcontext.Response.Body.Flush();
            }
        }

    }
}
